package gosee

import (
	"net/http"
	"strings"
)

type Middleware struct {
	keys     map[string]any
	handlers []HandlerFunc // 中间件链
	index    int           // 当前执行的中间件索引
	aborted  bool          // 是否已终止
}

// NewMiddleware 创建一个中间件
func NewMiddleware() *Middleware {
	return &Middleware{
		keys: make(map[string]any),
	}
}

// collectMiddlewares 收集所有适用的中间件（全局 + 路由组）
func collectMiddlewares(engine *Engine, r *http.Request) []HandlerFunc {
	var handlers []HandlerFunc

	// 1. 添加全局中间件（Engine 级别）
	handlers = append(handlers, engine.middlewares...)

	// 2. 按路径匹配路由组的中间件（从最具体的组开始）
	for _, group := range reverseGroupsByPrefixLength(engine.groups, r.URL.Path) {
		if strings.HasPrefix(r.URL.Path, group.prefix) {
			handlers = append(handlers, group.middlewares...)
		}
	}

	return handlers
}

// reverseGroupsByPrefixLength 按路由组前缀长度降序排序
func reverseGroupsByPrefixLength(groups []*RouterGroup, path string) []*RouterGroup {
	type groupWithLen struct {
		group *RouterGroup
		len   int
	}

	// 计算每个路由组与当前路径的匹配度
	weightedGroups := make([]groupWithLen, len(groups))
	for i, g := range groups {
		// 计算匹配的前缀长度
		matchLen := 0
		for i, c := range g.prefix {
			if i < len(path) && c == rune(path[i]) {
				matchLen++
			} else {
				break
			}
		}
		weightedGroups[i] = groupWithLen{group: g, len: matchLen}
	}

	// 按匹配长度降序排序
	for i := 0; i < len(weightedGroups); i++ {
		for j := i + 1; j < len(weightedGroups); j++ {
			if weightedGroups[i].len < weightedGroups[j].len {
				weightedGroups[i], weightedGroups[j] = weightedGroups[j], weightedGroups[i]
			}
		}
	}

	// 提取排序后的路由组
	sortedGroups := make([]*RouterGroup, len(weightedGroups))
	for i, w := range weightedGroups {
		sortedGroups[i] = w.group
	}

	return sortedGroups
}

// Abort 终止后续中间件的执行
func (m *Middleware) Abort() {
	m.aborted = true
}

// IsAborted 检查是否已终止
func (m *Middleware) IsAborted() bool {
	return m.aborted
}

// Next 执行中间件链中的下一个处理器
func (m *Middleware) Next(c *Context) {
	for m.index < len(m.handlers)-1 && !m.aborted {
		m.index++
		handler := m.handlers[m.index]
		handler(c)
	}
}

// Set 存储中间件数据
func (m *Middleware) Set(key string, value any) {
	if m.keys == nil {
		m.keys = make(map[string]any)
	}
	m.keys[key] = value
}

// Get 获取中间件数据
func (m *Middleware) Get(key string) (value any, exists bool) {
	value, exists = m.keys[key]
	return
}

// MustGet 获取中间件数据，不存在则panic
func (m *Middleware) MustGet(key string) any {
	if value, exists := m.Get(key); exists {
		return value
	}
	panic("Key \"" + key + "\" does not exist")
}
